/***************************************************************************
 *                                                                         *
 *   This file is part of the CrystalMem project,                          *
 *       http://code.google.com/p/crystalmem                               *
 *                                                                         *
 *   Copyright (C) 2008 by Alberto Scarpa <scarpa.alberto@gmail.com>       *
 *   Copyright (C) 2008 by Enrico Ros <enrico.ros@gmail.com>               *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include "MemoryView.h"
#include "MemoryTree.h"
#include <QDebug>
#include <QMimeData>
#include <QTimer>

#define notImplemented() { qWarning( "%s(%d): NOT IMPLEMENTED!", __FILE__, __LINE__ ); }

//BEGIN MemoryTreeItem
#include "WidgetItem.h"
class MemoryTreeItem : public WidgetItem {
    public:
        MemoryTreeItem( MemoryTree * memTree, QGraphicsItem * parent = 0 );

        // ::WidgetItem
        void paint( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0 );

    private:
        MemoryTree * m_memTree;
};

MemoryTreeItem::MemoryTreeItem( MemoryTree * memTree, QGraphicsItem * parent )
    : WidgetItem( parent )
    , m_memTree( memTree )
{
}

void MemoryTreeItem::paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget)
{
    if ( m_memTree ) {
        // TODO: add gui to choose/cycle rendering options
        MemoryTree::RenderOpts opts = MemoryTree::ShowBranches | MemoryTree::ShowAllocation;
        m_memTree->renderGL( QRect(x(), y(), width(), height()), opts );
    }
}
//END MemoryTreeItem

MemoryView::MemoryView( MemoryTree * memTree, QWidget * parentWidget )
    : GLGraphicsView( ":/data/bg.svg", ":/data/wm.png", parentWidget )
    , m_memTree( memTree )
    , m_inited( false )
{
    // customize layout
    setMinimumSize( 320, 20 );
    setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
    setAcceptDrops( true );
    setAutoRefresh( 50 );

    // NOTE: for testing: remove me
    //QTimer::singleShot( 1000, this, SLOT(slotTemp()));

    // create the graphics item that renders the current memorytree
    m_memTreeItem = new MemoryTreeItem( m_memTree, 0 );
    scene()->addItem( m_memTreeItem );
}

MemoryView::~MemoryView()
{
}

QSize MemoryView::sizeHint() const
{
    // this is the 'preferred' default size
    return QSize( 640, 480 );
}

void MemoryView::resizeEvent( QResizeEvent * event )
{
    // call parent implementation first
    GLGraphicsView::resizeEvent( event );

    // relayout items
    //QRect visualRect( 10, 10, width() - 70, height() - 70 );
    if ( m_memTreeItem ) {
        m_memTreeItem->move( 10, 10 );
        m_memTreeItem->resize( width() - 70, height() - 70 );
    }
}

void MemoryView::updateDynamics( double dT )
{
    if ( m_memTree )
        m_memTree->updateDynamics( dT );
}

void MemoryView::viewDrag( DragType /*dragType*/, QGraphicsSceneDragDropEvent * event )
{
    // don't accept unknown types
    if ( !event->mimeData()->text().startsWith( "memview_mimetype/" ) ) {
        event->ignore();
        return;
    }
    event->accept();
}

void MemoryView::keyPressed( const QString & keyText )
{
    // update the circular string
    m_lastKeys.prepend( keyText );
    if ( m_lastKeys.size() > 10 )
        m_lastKeys.chop( m_lastKeys.size() - 10 );

    // filter on that string
    // ... can perform actions on (reverse) text here
}

void MemoryView::slotTemp()
{
    // unused
    notImplemented();
}

